package com.bosssoft.gateway.service.filter;

import com.alibaba.fastjson.JSON;

import com.bosssoft.gateway.service.bo.UserBo;
import com.bosssoft.gateway.service.dao.mapper.WhiteAndBlackListMapper;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import common.exception.code.BizErrorCode;
import common.exception.parse.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @className: com.bosssoft.user.permission.center.LoginController
 * @description: 当前版本针对前端的页面实现相应的功能接口,特别说明如下：
 * 1、接口注解做参数非空等检查
 * 2、控制层不处理异常，异常交给统一异常处理
 * 3、控制层的返回参数被统一包转为公共类型
 * @author: lanyukai
 * @date: 2024/6/11 13:44
 * @since 1.0
 **/
@Slf4j
@RefreshScope
@RestController
@Component
public class DegradeModelWhiteListFilter implements GlobalFilter, Ordered {

    @Value("${system.run.level}")
    private String systemRunLevel;
    @Autowired
    private RedisTemplate redisTemplate;

    private final static String RUN_LEVEL_NORMAL = "Normal";
    private final static String RUN_LEVEL_DEGRADE = "Degrade";
    private final static String DegradeMSG = "系统已降级,您不可访问";
    private final static String BlACK_FORBIDDEN_MSG = "黑名单用户,不可访问";
    private final static String DegradeMSG2 = "服务已被熔断";

    @Autowired
    private WhiteAndBlackListMapper whiteAndBlackListMapper;

    @Override
    public int getOrder() {
        return 9999;
    }

    @HystrixCommand(fallbackMethod = "loginFallback")
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//        try {
//            Thread.sleep(1000);
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
//        }

        if (RUN_LEVEL_DEGRADE.equals(systemRunLevel)) {
            if (exchange.getRequest().getURI().toString().contains("/api/v1/permission/auth")) {
                MultiValueMap<String, String> userInfo = exchange.getRequest().getQueryParams();
                System.out.println(userInfo);
                if(userInfo.size()==0){
                    throw new BusinessException(BizErrorCode.DATA_SEARCH_NOT_FOUND, "输入错误");
                }
                UserBo userBO = new UserBo();
                userBO.setCode(userInfo.getFirst("code"));
                userBO.setPassword(userInfo.getFirst("password"));
                if(checkWhiteAndBlackList(userBO.getCode())==0){
                    return chain.filter(exchange);
                }else{
                    throw new BusinessException(BizErrorCode.DATA_SEARCH_NOT_FOUND, DegradeMSG);
                }
            } else {
                // 非登录界面 则解析token进一步做白名单判断
                //解析出token 如果有 判断token的用户是否白名单 是 则放行否则登录
                return chain.filter(exchange);
            }

        } else {
            if (exchange.getRequest().getURI().toString().contains("/api/v1/permission/auth")) {
                MultiValueMap<String, String> userInfo = exchange.getRequest().getQueryParams();
                System.out.println(userInfo);
                if(userInfo.size()==0){
                    throw new BusinessException(BizErrorCode.DATA_SEARCH_NOT_FOUND, "输入错误");
                }
                UserBo userBO = new UserBo();
                userBO.setCode(userInfo.getFirst("code"));
                userBO.setPassword(userInfo.getFirst("password"));

                if(checkWhiteAndBlackList(userBO.getCode())!=2){
                    return chain.filter(exchange);
                }else{
                    throw new BusinessException(BizErrorCode.DATA_SEARCH_NOT_FOUND, DegradeMSG);
                }
            } else {
                return chain.filter(exchange);
            }

        }
    }

    /**
     * 数据来源描述：用户中心增加黑白名单模块，界面增加黑白名后将黑白名单list对象存入redis<br>
     * 本方法主要操作描述： 从redis中取得判断是否存在黑名单存在则终止请求返回应答码否则放行
     *
     * @param
     * @return
     * status: 0-白名单 1-正常 2-黑名单 3-未找到
     */
    private Integer checkWhiteAndBlackList(String code) {
        Object o = redisTemplate.opsForValue().get("KEY_LOGIN" + "_" + code);
        if (!ObjectUtils.isEmpty(o)) {
            Integer whitelist = Integer.valueOf(o.toString());
            return whitelist;
        } else {
            Integer status = whiteAndBlackListMapper.selectWhiteAndBlacklist(code);
            redisTemplate.opsForValue().set("KEY_LOGIN" + "_" + code, status);
            return status;
        }
    }

    public Mono<Void> loginFallback(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("eee");
        log.info("服务已被熔断");
        throw new BusinessException(BizErrorCode.DATA_SEARCH_NOT_FOUND, DegradeMSG2);
    }
}
